// 版权归陈超所有

#pragma once

#include "CoreMinimal.h"
#include "AbilitySystemComponent.h"
#include "AttributeSet.h"
#include "CC_AttributeSet.generated.h"


/*要在游戏中使用它，您可以定义类似这样的内容，然后根据需要添加特定于游戏的功能：*/
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)

/*用于存储施放GE的相关对象和目标的相关对象*/
#pragma region FEffectProperties

USTRUCT()
struct FEffectProperties
{
	GENERATED_BODY()

	FEffectProperties(){}

	FGameplayEffectContextHandle EffectContextHandle;
	
	UPROPERTY()
	UAbilitySystemComponent* SourceASC = nullptr;

	UPROPERTY()
	AActor* SourceAvatarActor = nullptr;

	UPROPERTY()
	AController* SourceController = nullptr;

	UPROPERTY()
	ACharacter* SourceCharacter = nullptr;
	
	UPROPERTY()
	UAbilitySystemComponent* TargetASC = nullptr;

	UPROPERTY()
	AActor* TargetAvatarActor = nullptr;

	UPROPERTY()
	AController* TargetController = nullptr;

	UPROPERTY()
	ACharacter* TargetCharacter = nullptr;
};

#pragma endregion

/*
 * 模板函数:
 * 别名: 静态函数指针
 * 用途: 1. TMap(指针,属性)
 */
template<class T>
using TStaticFuncPtr = typename TBaseStaticDelegateInstance<T, FDefaultDelegateUserPolicy>::FFuncPtr;

/**
 * 
 */
UCLASS()
class CC_AURA_API UCC_AttributeSet : public UAttributeSet
{
	GENERATED_BODY()

public:
	UCC_AttributeSet();

	//属性更改前的方法
	virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;

	//属性更改后的方法
	virtual void PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data) override;

	/*
	 * TMap(指针,属性)
	 */
	TMap<FGameplayTag, TStaticFuncPtr<FGameplayAttribute()>> TagsToAttributes;

	
private:
	void SetEffectProperties(const struct FGameplayEffectModCallbackData& Data, FEffectProperties& Props) const;
/**************************************************************************************************************/
/**                                                     添加属性                                               **/
/**************************************************************************************************************/
public:
	// 用于声明哪些变量需要在服务器和客户端之间自动复制‌
	virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;

/*Vital属性:
*		1.获取角色等级
*/
#pragma region Vital Attributes
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Vital", ReplicatedUsing = OnRep_Health)
	FGameplayAttributeData Health;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Health);

	UPROPERTY(BlueprintReadOnly, Category="Attributes|Vital", ReplicatedUsing = OnRep_Mana)
	FGameplayAttributeData Mana;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Mana);

#pragma endregion


/**********************************************************************/

/*主要属性
	*1. Vigor: 体质
	*2. Agile: 敏捷
	*3. Strength: 力量
	*4. Intelligence: 智力
*/
#pragma region Primary Attributes
		
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Primary", ReplicatedUsing = OnRep_Vigor)
	FGameplayAttributeData Vigor;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Vigor);
	
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Primary", ReplicatedUsing = OnRep_Agile)
	FGameplayAttributeData Agile;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Agile);
		
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Primary", ReplicatedUsing = OnRep_Strength)
	FGameplayAttributeData Strength;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Strength);
	
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Primary", ReplicatedUsing = OnRep_Intelligence)
	FGameplayAttributeData Intelligence;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Intelligence);

#pragma endregion

/*次要属性:
 * 1. Armor: 护甲	减少受到的伤害, 提高格挡几率.
 *		- 受Agile影响
 *
 * 2. Armor Penetration: 护甲穿透	忽略敌人护甲的百分比, 增加暴击几率.
 *		- 受Agile影响
 *
 * 3. Block Chance: 格挡几率		有机会将受到的伤害减半.
 *		- 受Armor影响
 *
 * 4. Critical Hit Chance: 暴击几率		有机会获得双倍伤害并获得暴击加成
 *		- 受Armor Penetration影响
 *
 * 5. Critical Hit Damage: 暴击伤害		暴击时增加的额外伤害
 *		- 受Armor Penetration影响
 *
 * 6. Critical Hit Resistance: 暴击抗性		减少敌人攻击时的暴击几率
 *		- 受Armor影响
 *
 * 7. Health Regeneration: 生命回复		每秒回复的生命值
 *		- 受Vigor影响
 *
 * 8. Mana Regeneration: 魔法回复		每秒回复的魔法值
 *		- 受Intelligence影响
 *
 * 9. Max Health: 最大生命值
 *		- 受Vigor影响
 *
 * 10. Max Mana: 最大法力值
 *		- 受Intelligence影响
 */
	
#pragma region Secondary Attributes

	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_Armor)
	FGameplayAttributeData Armor;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Armor);
		
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_ArmorPenetration)
	FGameplayAttributeData ArmorPenetration;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, ArmorPenetration);
		
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_BlockChance)
	FGameplayAttributeData BlockChance;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, BlockChance);
	
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_CriticalHitChance)
	FGameplayAttributeData CriticalHitChance;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, CriticalHitChance);

	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_CriticalHitDamage)
	FGameplayAttributeData CriticalHitDamage;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, CriticalHitDamage);

	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_CriticalHitResistance)
	FGameplayAttributeData CriticalHitResistance;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, CriticalHitResistance);

	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_HealthRegeneration)
	FGameplayAttributeData HealthRegeneration;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, HealthRegeneration);

	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_ManaRegeneration)
	FGameplayAttributeData ManaRegeneration;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, ManaRegeneration);
	
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_MaxHealth)
	FGameplayAttributeData MaxHealth;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, MaxHealth);
	
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_MaxMana)
	FGameplayAttributeData MaxMana;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, MaxMana);

#pragma endregion
	
/*********************************************************************
 * 复制回调函数
 */
#pragma region OnRep_Fuc
	
	UFUNCTION()
	void OnRep_ManaRegeneration(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_HealthRegeneration(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_CriticalHitResistance(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_CriticalHitDamage(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_CriticalHitChance(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_BlockChance(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_ArmorPenetration(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_Armor(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_Health(const FGameplayAttributeData& OldValue) const;

	UFUNCTION()
	void OnRep_MaxHealth(const FGameplayAttributeData& OldValue) const;

	UFUNCTION()
	void OnRep_Mana(const FGameplayAttributeData& OldValue) const;

	UFUNCTION()
	void OnRep_MaxMana(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_Intelligence(const FGameplayAttributeData& OldValue) const;

	UFUNCTION()
	void OnRep_Agile(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_Strength(const FGameplayAttributeData& OldValue) const;
		
	UFUNCTION()
	void OnRep_Vigor(const FGameplayAttributeData& OldValue) const;
	
#pragma endregion
	
/**************************************************************************************************************/
};
